from typing import List, Union, Dict

from emi.bar.data import CategoryMeta, SymbolMeta, CategorySymbolMeta
from emi.bar.db import  BarDB, DayDB, RankDB
from emi.bar.storage import RankStorage
from emi.model import Market


class SimpleMarket:
    """
    SimpleMarket 是一个简化版市场行情对象。(只考虑个股和单一行业的情况）
    包含：个股行情，行业行情，个股排名、行业排名
    """

    def __init__(self, market:Market,category_type:int):
        self._base_market = market
        self.market_meta = self._base_market.get_meta()
        self._CATEGORY_TYPE = category_type
        self.ALL_SYMBOL_META_MAP = self.market_meta.get_all_symbol_metas(as_map=True)
        self.ALL_CATEGORY_META_MAP = self.market_meta.get_all_category_metas(as_map=True, type=self._CATEGORY_TYPE)

    def get_index_bar_db(self)->BarDB:
        """
        返回大盘指数历史行情数据。 具体大盘可以查看：MarketIndex里面的枚举值
        :return:
        """
        return self._base_market.get_index_bar_db()

    def get_index_today_db(self)->DayDB:
        """
        返回大盘指数实时行情数据。 具体大盘可以查看：MarketIndex里面的枚举值
        :return:
        """
        return self._base_market.get_index_today_db()

    def getRankDB(self, category: bool = False) -> RankStorage:
        """
        返回市场的排名数据
        :category
             是否为行业分类数据
        :return:
        """
        raise NotImplementedError()

    def get_bar_db(self, category: bool = False) -> BarDB:
        """
        返回历史行情数据:（适合按个股遍历）
        :category
            是否为行业分类数据
        """
        market = self._base_market
        if category:
            return market.get_bar_db(category_type=self._CATEGORY_TYPE)
        return market.get_bar_db()

    def get_today_db(self, category: bool = False) -> DayDB:
        """
        返回今天的实时行情数据。
        行业元组数据:
        :category
             是否为行业分类数据
        """
        market = self._base_market
        if category:
            return market.get_today_db(category_type=self._CATEGORY_TYPE)
        return market.get_today_db()



    ###------- 以下是相关行业分类和个股结构信息。

    def get_all_category_metas(self, as_map=False) -> Union[List[CategoryMeta], Dict[str, CategoryMeta]]:
        """
        返回所有的行业分类。
        :param as_map: 是否返回map对象
        :return:
        """
        if as_map:
            return self.ALL_CATEGORY_META_MAP
        return list(self.ALL_CATEGORY_META_MAP.values())

    def get_all_symbol_metas(self, as_map=False) -> Union[List[SymbolMeta], Dict[str, SymbolMeta]]:
        """
        返回所有的个股结构信息。
        :param as_map: 是否返回map对象
        :return:
        """
        if as_map:
            return self.ALL_SYMBOL_META_MAP
        return list(self.ALL_SYMBOL_META_MAP.values())

    def get_category_metas_by_symbol(self, symbol) -> List[CategoryMeta]:
        """
        返回个股所属分类行业信息
        :param symbol:
        :return:
        """
        return self.market_meta.get_category_metas_by_symbol(symbol=symbol, type=self._CATEGORY_TYPE)

    def get_category_symbol_metas(self, category_code: str, as_map=False) -> Union[
        List[CategorySymbolMeta], Dict[str, CategorySymbolMeta]]:
        """
        返回分类下的所有个股信息
        :param category_code:
        :return:
        """
        return self.market_meta.get_category_symbol_metas(category_code=category_code, as_map=as_map)

    def get_category_meta(self, codes:Union[str,List[str]],as_map = False) -> Union[CategoryMeta,List[CategoryMeta],CategoryMeta]:
        """
        返回分类行业信息
        :param codes: 行业分类代码
        :return:
        """
        all_map = self.get_all_category_metas(as_map=True)
        if isinstance(codes,str):
            return all_map.get(codes)

        if as_map:
            ret = {}
        else:
            ret = []
        for code in codes:
            meta = all_map.get(code)
            if meta:
                if as_map:
                    ret[code] = meta
                else:
                    ret.append(meta)
        return ret

    def get_symbol_meta(self,codes:Union[str,List[str]],as_map=False)-> Union[SymbolMeta,List[SymbolMeta], Dict[str, SymbolMeta],SymbolMeta]:
        """
        获取个股信息。
        :param codes:
        :param as_map:
        :return:
        """
        all_map = self.get_all_symbol_metas(as_map=True)
        if isinstance(codes, str):
            return all_map.get(codes)
        if as_map:
            ret = {}
        else:
            ret = []
        for code in codes:
            meta  = all_map.get(code)
            if meta:
                if as_map:
                    ret[code] = meta
                else:
                    ret.append(meta)
        return ret

    def get_symbol_name(self,code:str,default_name:str = None):
        """
        返回个股名称
        :param code:
        :return:
        """
        meta = self.get_all_symbol_metas(as_map=True).get(code)
        if meta:
            return meta.name
        return default_name

    def get_category_name(self,code:str,default_name:str = None):
        """
        返回行业名称。
        :param code:
        :return:
        """
        meta = self.get_all_category_metas(as_map=True).get(code)
        if meta:
            return meta.name
        return default_name